<?php

namespace App\X;


use App\Common\Log;
use XWX\Common\Traits\TraitIns;

class XContext
{
    use TraitIns;


    private $context = [];


    /**
     * 设置一个值
     *
     * @param      $key
     * @param      $value
     * @param null $cid
     * @return XContext
     */
    public function set($key, $value, $cid = null)
    {
        $cid = $this->getCoroutineID($cid);
        $this->context[$cid][$key] = $value;

        return $this;
    }


    /**
     * 获取一个值,如果使用XDataBase,还会调用XDataBase的funcGetDB方法
     *
     * @param $key
     * @param null $cid
     *
     * @return mixed|null
     * @throws \Exception
     */
    public function get($key, $cid = null)
    {
        $cid = $this->getCoroutineID($cid);

        if (isset($this->context[$cid][$key]))
        {
            $val = $this->context[$cid][$key];
            if ($val instanceof XDataBase)
            {
                return $val->funcGetDB();
            }
            else
            {
                return $this->context[$cid][$key];
            }
        }


        return null;
    }

    /**
     * 获取当前协程所有变量
     *
     * @param null $cid
     * @return array|null
     */
    public function getAll($cid = null)
    {
        $cid = $this->getCoroutineID($cid);
        if (isset($this->context[$cid]))
        {
            return $this->context[$cid];
        }
        else
        {
            return null;
        }
    }


    /**
     * 删除一个值,如果是使用XDataBase,还会调用XDataBase的funcRecycle方法
     *
     * @param $key
     * @param null $cid
     *
     * @return bool
     * @throws \Throwable
     */
    private function unset($key, $cid = null)
    {
        $cid = $this->getCoroutineID($cid);

        if (isset($this->context[$cid][$key]))
        {
            $val = $this->context[$cid][$key];
            if ($val instanceof XDataBase)
            {
                $val->funcRecycle();
            }

            unset($this->context[$cid][$key]);

            return true;
        }
        else
        {
            return false;
        }
    }


    /**
     * 销毁当前协程所有值
     *
     * @param null $cid
     * @throws \Throwable
     */
    public function destroy($cid = null)
    {
        $cid = $this->getCoroutineID($cid);
        Log::funcLogDebug(__METHOD__, "BEGIN");

        if (isset($this->context[$cid]))
        {
            $data = $this->context[$cid];
            foreach ($data as $key => $val)
            {
                $this->unset($key, $cid);
            }
        }
        unset($this->context[$cid]);

        Log::funcLogDebug(__METHOD__, "END");
    }

    /**
     * 清空所有值
     *
     * @param bool $force
     * @throws \Throwable
     */
    public function destroyAll($force = false)
    {
        if ($force)
        {
            $this->context = [];
        }
        else
        {
            foreach ($this->context as $cid => $data)
            {
                $this->destroy($cid);
            }
        }
    }


    /**
     * 获取当前协程id
     *
     * @param null $cid
     * @return int
     */
    public function getCoroutineID($cid = null): int
    {
        if ($cid === null)
        {
            return \Swoole\Coroutine::getUid();
        }
        return $cid;
    }
}